﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace GDI_应用案例.Pages.Controls
{
    /// <summary>
    /// 曼德勃罗集
    /// </summary>
    internal unsafe class Mandelbrot
    {
        // 图像大小
        private Size _size = new Size(400, 400);
        // 最大迭代此数
        private int _maxIterations = 100;
        // 基色
        private Color _baseColor = Color.Beige;
        public Mandelbrot()
            : this(new Size(400, 400))
        {
        }
        public Mandelbrot(Size size)
        {
            this._size = size;
        }
        public int MaxIterations
        {
            get { return _maxIterations; }
            set { _maxIterations = value; }
        }
        public Complex Start { get; set; } = new Complex(-2, -2);// 迭代起始点
        public Complex End { get; set; }= new Complex(2, 2);
        public IRenderSpot RenderSpot { get; set; }
        public IIterationRules PolynomialRules { get; set; }
        public IIterationRules OtherRules { get; set; }
        public Bitmap DrawMandel(int n = 0, string txt = "")
        {
            Bitmap b = new Bitmap(_size.Width, _size.Height);
            Rectangle rect = new Rectangle(0, 0, b.Width, b.Height);
            BitmapData bmpData = b.LockBits(rect, ImageLockMode.WriteOnly, b.PixelFormat);
            int bytes = Math.Abs(bmpData.Stride) * b.Height;
            byte* ptr = (byte*)bmpData.Scan0;
            Complex delta = new Complex((End.Real - Start.Real) / _size.Width, (End.Imaginary - Start.Imaginary) / _size.Height);
            // 定义委托类型
            Func<Complex, Complex> iterationRulesDelegate = null;
            if (PolynomialRules != null)
                iterationRulesDelegate += (complex) => PolynomialRules.GetIterationRules(complex, n);
            if (OtherRules != null)
                iterationRulesDelegate += (complex) => OtherRules.GetIterationRules(complex, txt);

            Parallel.For(0, _size.Height, j =>
            {
                double imaginary = Start.Imaginary + j * delta.Imaginary;
                byte* ptrTemp = stackalloc byte[4];
                int js = j * bmpData.Stride;
                for (int i = 0; i < _size.Width; i++)
                {
                    double real = Start.Real + i * delta.Real;
                    int iter = 0;
                    Complex c = new Complex();
                    Complex spot = new Complex(real, imaginary);
                    while (iter < _maxIterations && c.Magnitude < 2)
                    {
                        iter++;
                        c = iterationRulesDelegate(c) + spot;
                    }
                    RenderSpot.RenderSpot(c, iter, _baseColor, this.MaxIterations, ptrTemp);
                    int index = js + (i << 2);
                    Buffer.MemoryCopy(ptrTemp, ptr + index, 4, 4);
                }
            });
            b.UnlockBits(bmpData);

            return b;
        }
    }

    interface IIterationRules
    {
        Complex GetIterationRules(Complex c, params object[] objects);
    }
    class PolynomialRules : IIterationRules
    {
        public Complex GetIterationRules(Complex c, params object[] objects) => Complex.Pow(c, (int)objects[0]);
    }
    class OtherRules : IIterationRules
    {
        public Complex GetIterationRules(Complex c, params object[] objects)
        {
            string txt = objects[0].ToString();
            Complex result = Complex.Zero;
            if ("Sin".Equals(txt))
                result = Complex.Sin(c);
            else if ("Sinh".Equals(txt))
                result = Complex.Sinh(c);
            else if ("Asin".Equals(txt))
                result = Complex.Asin(c);
            else if ("Cos".Equals(txt))
                result = Complex.Cos(c);
            else if ("Cosh".Equals(txt))
                result = Complex.Cosh(c);
            else if ("Acos".Equals(txt))
                result = Complex.Acos(c);
            else if ("Tan".Equals(txt))
                result = Complex.Tan(c);
            else if ("Tanh".Equals(txt))
                result = Complex.Tanh(c);
            else if ("Atan".Equals(txt))
                result = Complex.Atan(c);
            else if ("Log".Equals(txt))
                result = Complex.Log(c);
            else if ("Log10".Equals(txt))
                result = Complex.Log10(c);
            else if ("Exp".Equals(txt))
                result = Complex.Exp(c);
            else if ("Sqrt".Equals(txt))
                result = Complex.Sqrt(c);
            else
                result = Complex.Pow(c, c);

            return result;
        }
    }


    unsafe interface IRenderSpot
    {
        void RenderSpot(Complex ret, int i, Color baseColor, int maxIterations,byte* ptr);
    }
    unsafe class  RenderSpotTradition : IRenderSpot
    {
        public unsafe void RenderSpot(Complex ret, int i, Color baseColor, int maxIterations, byte* ptr)
        {
            float Kn2 = 0f;//渐变调节参数
            int colorR = 0x100 - Math.Abs((int)((((int)Math.Abs((double)(baseColor.R - (((2 * baseColor.G) - 0x100) * (Math.Sqrt((double)Math.Abs(i)) * Math.Pow(2.0, (double)Kn2)))))) % 0x200) - 0x100));

            int colorG = 0x100 - Math.Abs((int)((((int)Math.Abs((double)(baseColor.G - ((((2 * baseColor.B) - 0x100) * Math.Log(ret.Magnitude)) * Math.Pow(2.0, (double)Kn2))))) * 0x200) - 0x100));

            int colorB = 0x100 - Math.Abs((int)((((int)Math.Abs((double)(baseColor.B - ((((2 * baseColor.R) - 0x100) * Math.Log(Math.Abs((double)((100 - i) + ret.Real)))) * Math.Pow(2.0, (double)Kn2))))) * 0x200) - 0x100));

            *ptr = (byte)Math.Max(0, Math.Min(0xff, colorB));
            *(ptr + 1) = (byte)Math.Max(0, Math.Min(0xff, colorG));
            *(ptr + 2) = (byte)Math.Max(0, Math.Min(0xff, colorR));
            *(ptr + 3) = 255;
        }
    }
    class RenderSpotHSV : IRenderSpot
    {
        public Color RenderSpot(Complex ret, int i, Color baseColor, int maxIterations)
        {
            if (i == maxIterations)
            {
                return Color.Black; // 曼德勃罗集内部的点
            }

            // 使用HSV颜色空间生成渐变
            double hue = (i % 360) / 360.0; // 色相在0到1之间
            double saturation = 1.0; // 饱和度
            double value = 1.0; // 明度

            // 将HSV转换为RGB
            int hi = (int)(Math.Floor(hue * 6)) % 6;
            double f = hue * 6 - Math.Floor(hue * 6);
            double p = value * (1 - saturation);
            double q = value * (1 - f * saturation);
            double t = value * (1 - (1 - f) * saturation);

            double r, g, b;
            switch (hi)
            {
                case 0: r = value; g = t; b = p; break;
                case 1: r = q; g = value; b = p; break;
                case 2: r = p; g = value; b = t; break;
                case 3: r = p; g = q; b = value; break;
                case 4: r = t; g = p; b = value; break;
                case 5: r = value; g = p; b = q; break;
                default: r = g = b = 0; break;
            }

            return Color.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255));
        }

        public unsafe void RenderSpot(Complex ret, int i, Color baseColor, int maxIterations, byte* ptr)
        {
            if (i == maxIterations)
            {
                *ptr = (byte)0;
                *(ptr + 1) = (byte)0;
                *(ptr + 2) = (byte)0;
                *(ptr + 3) = 255;
                return; // 曼德勃罗集内部的点
            }

            // 使用HSV颜色空间生成渐变
            double hue = (i % 360) / 360.0; // 色相在0到1之间
            double saturation = 1.0; // 饱和度
            double value = 1.0; // 明度

            // 将HSV转换为RGB
            int hi = (int)(Math.Floor(hue * 6)) % 6;
            double f = hue * 6 - Math.Floor(hue * 6);
            double p = value * (1 - saturation);
            double q = value * (1 - f * saturation);
            double t = value * (1 - (1 - f) * saturation);

            double r, g, b;
            switch (hi)
            {
                case 0: r = value; g = t; b = p; break;
                case 1: r = q; g = value; b = p; break;
                case 2: r = p; g = value; b = t; break;
                case 3: r = p; g = q; b = value; break;
                case 4: r = t; g = p; b = value; break;
                case 5: r = value; g = p; b = q; break;
                default: r = g = b = 0; break;
            }

            *ptr = (byte)(b * 255);
            *(ptr + 1) = (byte)(g * 255);
            *(ptr + 2) = (byte)(r * 255);
            *(ptr + 3) = 255;
        }
    }
    class RenderSpotLog : IRenderSpot
    {
        public Color RenderSpot(Complex ret, int i, Color baseColor, int maxIterations)
        {
            if (i == maxIterations)
            {
                return Color.Black; // 曼德勃罗集内部的点
            }

            // 使用对数渐变
            double logIter = Math.Log(i + 1);
            double colorValue = logIter / Math.Log(maxIterations);

            // 将颜色值映射到RGB
            int r = (int)(255 * colorValue);
            int g = (int)(255 * (1 - colorValue));
            int b = (int)(255 * (1 - colorValue));

            return Color.FromArgb(r, g, b);
        }

        public unsafe void RenderSpot(Complex ret, int i, Color baseColor, int maxIterations, byte* ptr)
        {
            if (i == maxIterations)
            {
                *ptr = (byte)0;
                *(ptr + 1) = (byte)0;
                *(ptr + 2) = (byte)0;
                *(ptr + 3) = 255;
                return; // 曼德勃罗集内部的点
            }

            // 使用对数渐变
            double logIter = Math.Log(i + 1);
            double colorValue = logIter / Math.Log(maxIterations);

            // 将颜色值映射到RGB
            int r = (int)(255 * colorValue);
            int g = (int)(255 * (1 - colorValue));
            int b = (int)(255 * (1 - colorValue));

            *ptr = (byte)b;
            *(ptr + 1) = (byte)g;
            *(ptr + 2) = (byte)r;
            *(ptr + 3) = 255;
        }
    }
    class RenderSpotSmooth : IRenderSpot
    {
        public Color RenderSpot(Complex ret, int i, Color baseColor, int maxIterations)
        {
            if (i == maxIterations)
            {
                return Color.Black; // 曼德勃罗集内部的点
            }

            // 使用平滑渐变
            double t = (double)i / maxIterations;
            int r = (int)(9 * (1 - t) * t * t * t * 255);
            int g = (int)(15 * (1 - t) * (1 - t) * t * t * 255);
            int b = (int)(8.5 * (1 - t) * (1 - t) * (1 - t) * t * 255);

            return Color.FromArgb(r, g, b);
        }

        public unsafe void RenderSpot(Complex ret, int i, Color baseColor, int maxIterations, byte* ptr)
        {
            if (i == maxIterations)
            {
                *ptr = (byte)0;
                *(ptr + 1) = (byte)0;
                *(ptr + 2) = (byte)0;
                *(ptr + 3) = 255;
                return; // 曼德勃罗集内部的点
            }

            // 使用平滑渐变
            double t = (double)i / maxIterations;
            int r = (int)(9 * (1 - t) * t * t * t * 255);
            int g = (int)(15 * (1 - t) * (1 - t) * t * t * 255);
            int b = (int)(8.5 * (1 - t) * (1 - t) * (1 - t) * t * 255);

            *ptr = (byte)b;
            *(ptr + 1) = (byte)g;
            *(ptr + 2) = (byte)r;
            *(ptr + 3) = 255;
        }
    }
    class RenderSpotPredefine : IRenderSpot
    {
        // 预定义的颜色表
        Color[] colorTable = new Color[]
        {
        Color.FromArgb(66, 30, 15),
        Color.FromArgb(25, 7, 26),
        Color.FromArgb(9, 1, 47),
        Color.FromArgb(4, 4, 73),
        Color.FromArgb(0, 7, 100),
        Color.FromArgb(12, 44, 138),
        Color.FromArgb(24, 82, 177),
        Color.FromArgb(57, 125, 209),
        Color.FromArgb(134, 181, 229),
        Color.FromArgb(211, 236, 248),
        Color.FromArgb(241, 233, 191),
        Color.FromArgb(248, 201, 95),
        Color.FromArgb(255, 170, 0),
        Color.FromArgb(204, 128, 0),
        Color.FromArgb(153, 87, 0),
        Color.FromArgb(106, 52, 3)
        };

        public Color RenderSpot(Complex ret, int i, Color baseColor, int maxIterations)
        {
            if (i == maxIterations)
            {
                return Color.Black; // 曼德勃罗集内部的点
            }

            // 根据迭代次数选择颜色
            int index = i % colorTable.Length;
            return colorTable[index];
        }

        public unsafe void RenderSpot(Complex ret, int i, Color baseColor, int maxIterations, byte* ptr)
        {
            if (i == maxIterations)
            {
                *ptr = (byte)0;
                *(ptr + 1) = (byte)0;
                *(ptr + 2) = (byte)0;
                *(ptr + 3) = 255;
                return; // 曼德勃罗集内部的点
            }

            int index = i % colorTable.Length;
            var c= colorTable[index];
            *ptr = (byte)c.B;
            *(ptr + 1) = (byte)c.G;
            *(ptr + 2) = (byte)c.R;
            *(ptr + 3) = c.A;
        }
    }
    class RenderSpotGray : IRenderSpot
    {
        public Color RenderSpot(Complex ret, int i, Color baseColor, int maxIterations)
        {
            if (i == maxIterations)
            {
                return Color.Black; // 曼德勃罗集内部的点
            }

            // 使用灰度渐变
            int gray = (int)(255 * (double)i / maxIterations);
            return Color.FromArgb(gray, gray, gray);
        }

        public unsafe void RenderSpot(Complex ret, int i, Color baseColor, int maxIterations, byte* ptr)
        {
            if (i == maxIterations)
            {
                *ptr = (byte)0;
                *(ptr + 1) = (byte)0;
                *(ptr + 2) = (byte)0;
                *(ptr + 3) = 255;
                return; // 曼德勃罗集内部的点
            }
            // 使用灰度渐变
            int gray = (int)(255 * (double)i / maxIterations);
            *ptr = (byte)gray;
            *(ptr + 1) = (byte)gray;
            *(ptr + 2) = (byte)gray;
            *(ptr + 3) = 255;
        }
    }
}
